package com.ruoyi.message.service.impl;

import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.message.domain.MessageBody;
import com.ruoyi.message.domain.MessageBodyRestDO;
import com.ruoyi.message.domain.MessageReceive;
import com.ruoyi.message.mapper.MessageMapper;
import com.ruoyi.message.menu.MessageReceiveType;
import com.ruoyi.message.menu.MessageStatus;
import com.ruoyi.message.service.IMessageService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 消息service实现类
 *
 * @author liuyu
 */
@Service
public class MessageServiceImpl implements IMessageService {

    @Autowired
    private MessageMapper messageMapper;

    /**
     * 发送消息
     *
     * @param messageBody 消息主体
     */
    public void sendMessage(MessageBody messageBody) {
        if (null != messageBody.getMessageType()) {
            if (MessageReceiveType.USER.getValue().equals(messageBody.getMessageType())) {
                this.sendMessageToUser(messageBody);
            } else if (MessageReceiveType.DEPT.getValue().equals(messageBody.getMessageType())) {
                this.sendMessageToDept(messageBody);
            } else if (MessageReceiveType.ROLE.getValue().equals(messageBody.getMessageType())) {
                this.sendMessageToRole(messageBody);
            } else if (MessageReceiveType.POST.getValue().equals(messageBody.getMessageType())) {
                this.sendMessageToPost(messageBody);
            } else {
                throw new CustomException("不支持对用户、部门、角色以外的类型发送消息");
            }
        } else {
            throw new CustomException("数据错误，消息主体中收件人类型为空");
        }
    }

    /**
     * 给指定人发送消息
     *
     * @param messageBody 消息主体
     */
    public void sendMessageToUser(MessageBody messageBody) {
        messageBody.setMessageType(MessageReceiveType.USER.getValue());
        setCreateBy(messageBody);
        this.messageMapper.insertMessageBody(messageBody);
        String receiver = messageBody.getReceiver();
        List<MessageReceive> messageReceiveList = new ArrayList<>();
        if (StringUtils.isNotBlank(receiver)) {
            Stream.of(receiver.split(",")).forEach(r -> {
                MessageReceive messageReceive = new MessageReceive();
                messageReceive.setMessageId(messageBody.getId());
                messageReceive.setMessageTo(Long.valueOf(r));
                messageReceive.setStatus(MessageStatus.UNREAD.getValue());
                messageReceiveList.add(messageReceive);
            });
        }
        if (CollectionUtils.isNotEmpty(messageReceiveList)) {
            this.messageMapper.insertBatchMessageReceive(messageReceiveList);
        }
    }

    /**
     * 给指定部门发送消息
     *
     * @param messageBody 消息主体
     */
    public void sendMessageToDept(MessageBody messageBody) {
        messageBody.setMessageType(MessageReceiveType.DEPT.getValue());
        setCreateBy(messageBody);
        this.messageMapper.insertMessageBody(messageBody);
        String receiver = messageBody.getReceiver();
        List<MessageReceive> messageReceiveList = new ArrayList<>();
        if (StringUtils.isNotBlank(receiver)) {
            Stream.of(receiver.split(",")).forEach(r -> {
                List<Long> sysUserIdList = this.messageMapper.selectUserListByDeptIdRecursive(Long.valueOf(r));
                sysUserIdList.forEach(userId -> {
                    MessageReceive messageReceive = new MessageReceive();
                    messageReceive.setMessageId(messageBody.getId());
                    messageReceive.setMessageTo(userId);
                    messageReceive.setStatus(MessageStatus.UNREAD.getValue());
                    messageReceiveList.add(messageReceive);
                });
            });
        }
        if (CollectionUtils.isNotEmpty(messageReceiveList)) {
            this.messageMapper.insertBatchMessageReceive(messageReceiveList);
        }
    }

    /**
     * 给指定角色发送消息
     *
     * @param messageBody 消息主体
     */
    public void sendMessageToRole(MessageBody messageBody) {
        messageBody.setMessageType(MessageReceiveType.ROLE.getValue());
        setCreateBy(messageBody);
        this.messageMapper.insertMessageBody(messageBody);
        String receiver = messageBody.getReceiver();
        List<MessageReceive> messageReceiveList = new ArrayList<>();
        if (StringUtils.isNotBlank(receiver)) {
            Stream.of(receiver.split(",")).forEach(r -> {
                List<Long> sysUserIdList = this.messageMapper.selectUserListByRoleId(Long.valueOf(r));
                sysUserIdList.forEach(userId -> {
                    MessageReceive messageReceive = new MessageReceive();
                    messageReceive.setMessageId(messageBody.getId());
                    messageReceive.setMessageTo(userId);
                    messageReceive.setStatus(MessageStatus.UNREAD.getValue());
                    messageReceiveList.add(messageReceive);
                });
            });
        }
        if (CollectionUtils.isNotEmpty(messageReceiveList)) {
            this.messageMapper.insertBatchMessageReceive(messageReceiveList);
        }
    }

    /**
     * 给指定岗位发送消息
     *
     * @param messageBody 消息主体
     */
    public void sendMessageToPost(MessageBody messageBody) {
        messageBody.setMessageType(MessageReceiveType.ROLE.getValue());
        setCreateBy(messageBody);
        this.messageMapper.insertMessageBody(messageBody);
        String receiver = messageBody.getReceiver();
        List<MessageReceive> messageReceiveList = new ArrayList<>();
        if (StringUtils.isNotBlank(receiver)) {
            Stream.of(receiver.split(",")).forEach(r -> {
                List<Long> sysUserIdList = this.messageMapper.selectUserListByPostId(Long.valueOf(r));
                sysUserIdList.forEach(userId -> {
                    MessageReceive messageReceive = new MessageReceive();
                    messageReceive.setMessageId(messageBody.getId());
                    messageReceive.setMessageTo(userId);
                    messageReceive.setStatus(MessageStatus.UNREAD.getValue());
                    messageReceiveList.add(messageReceive);
                });
            });
        }
        if (CollectionUtils.isNotEmpty(messageReceiveList)) {
            this.messageMapper.insertBatchMessageReceive(messageReceiveList);
        }
    }

    /**
     * 查询自己的消息
     *
     * @return 自己的消息列表
     */
    @Override
    public List<MessageBody> getMessageListToMyself() {
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        return this.messageMapper.selectMessageListToMyself(sysUser.getUserId());
    }

    /**
     * 查询自己收到的消息
     *
     * @param status 状态
     * @return 自己的消息列表
     */
    public List<MessageBody> getMessageListToMyself(MessageStatus status) {
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        return this.messageMapper.getMessageListToMyself(sysUser.getUserId(), status.getValue());
    }

    /**
     * 查询自己发送的消息
     *
     * @return 发送的消息列表
     */
    @Override
    public List<MessageBody> getMessageListSendFromMe() {
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        MessageBody query = new MessageBody();
        query.setMessageFrom(sysUser.getUserId());
        return this.messageMapper.selectMessageList(query);
    }

    /**
     * 通过ID查询消息详情
     *
     * @param id 消息ID
     * @return 消息
     */
    @Override
    public MessageBody getMessageById(Long id) {
        return messageMapper.selectMessageBodyById(id);
    }

    /**
     * 删除消息
     *
     * @param id 消息主体ID
     */
    public void deleteMessageBodyById(Long id) {
        messageMapper.deleteMessageReceiveByMessageId(id);
        messageMapper.deleteMessageBodyById(id);
    }

    /**
     * 标记已读状态
     *
     * @param id 业务ID
     * @return 返回结果
     */
    public int readMark(Long id, String status) {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        return messageMapper.readMark(id, user.getUserId(), status);
    }

    /**
     * 给消息主体赋值创建时间、创建人等信息
     *
     * @param messageBody 消息主体
     * @return 消息主体
     */
    private MessageBody setCreateBy(MessageBody messageBody) {
        //权限相关字段赋值
        try {
            SysUser loginUser = SecurityUtils.getLoginUser().getUser();
            messageBody.setCreateBy(loginUser.getUserName());
            messageBody.setAclCreateById(loginUser.getUserId());
            messageBody.setAclDeptId(loginUser.getDeptId());
        } catch (CustomException ignored) {
            // 允许获取不到当前用户情况（定时任务需要发消息）
        }
        messageBody.setCreateTime(DateUtils.getNowDate());
        return messageBody;
    }

    /**
     * 接收推送的消息
     *
     * @param messageBodyRestDO 消息主体
     * @return 返回信息
     */
    public void receiveRestMessage(MessageBodyRestDO messageBodyRestDO) {
        if (messageBodyRestDO.getMessageType() == null) {
            messageBodyRestDO.setMessageType(MessageReceiveType.USER.getValue());
        }
        //权限相关字段赋值
        try {
            SysUser loginUser = SecurityUtils.getLoginUser().getUser();
            messageBodyRestDO.setCreateBy(loginUser.getUserName());
            messageBodyRestDO.setAclCreateById(loginUser.getUserId());
        } catch (CustomException ignored) {
            // 允许获取不到当前用户情况（定时任务需要发消息）
        }
        messageBodyRestDO.setCreateTime(DateUtils.getNowDate());

        // Rest接口接收消息主体转成可以保存的消息类型
        MessageBody messageBody = messageBodyRestDO.toMessageBody();

        // 根据发送人用户名查询ID
        Long messageForm = messageMapper.selectUserIdListByUserName(messageBodyRestDO.getMessageFrom());
        if (null == messageForm) {
            throw new CustomException(String.format("消息发送人错误，无法查询到用户名为【%s】的用户", messageBodyRestDO.getMessageFrom()));
        }
        if (null == messageBody.getCreateBy()) {
            messageBody.setCreateBy(messageBodyRestDO.getMessageFrom());
        }
        if (null == messageBody.getAclCreateById()) {
            messageBody.setAclCreateById(messageForm);
        }
        messageBody.setMessageFrom(messageForm);

        // 根据接收人用户名查询接收人ID
        List<Long> receivers = messageMapper.selectUserIdListByUserNames(messageBodyRestDO.getReceiver().split(","));
        if (CollectionUtils.isEmpty(receivers)) {
            throw new CustomException(String.format("消息接收人错误，无法查询到对应用户名为【%s】的用户", messageBodyRestDO.getReceiver()));
        }
        messageBody.setReceiver(receivers.stream().map(String::valueOf).collect(Collectors.joining(",")));

        this.messageMapper.insertMessageBody(messageBody);
        String receiver = messageBody.getReceiver();
        List<MessageReceive> messageReceiveList = new ArrayList<>();
        if (StringUtils.isNotBlank(receiver)) {
            Stream.of(receiver.split(",")).forEach(r -> {
                MessageReceive messageReceive = new MessageReceive();
                messageReceive.setMessageId(messageBody.getId());
                messageReceive.setMessageTo(Long.valueOf(r));
                messageReceive.setStatus(MessageStatus.UNREAD.getValue());
                messageReceiveList.add(messageReceive);
            });
        }
        this.messageMapper.insertBatchMessageReceive(messageReceiveList);
    }

    /**
     * 查询推送的用户类型的消息（外部接口推送查询使用）
     *
     * @return 消息列表
     */
    public List<MessageBodyRestDO> selectMessageRestDOList(MessageBodyRestDO messageBodyRestDO) {
        List<MessageBodyRestDO> messageBodyRestDOS = messageMapper.selectMessageRestDOList(messageBodyRestDO);
        messageBodyRestDOS.forEach(m -> {
            String receiver = m.getReceiver();
            if (StringUtils.isNotBlank(receiver)) {
                String[] receiverIdsStr = receiver.split(",");
                if (receiverIdsStr.length > 0) {
                    Long[] receiverIds = Arrays.stream(receiverIdsStr).map(Long::valueOf).collect(Collectors.toList()).toArray(new Long[receiverIdsStr.length]);
                    List<String> usernames = messageMapper.selectUserNameListByUserIds(receiverIds);
                    m.setReceiver(String.join(",", usernames));
                }
            }
        });
        return messageBodyRestDOS;
    }
}
